"""
Describes a common set of plugins, including IMDB, 
Metacritic, Rotten Tomatoes, etc.
"""

import base
import urllib

class BasicPlugin(base.Plugin):
    def __init__(self, plugName, plugURL, plugBase, plugHeader, movie=True):
        """ Constructs a movie plugin for convenience. """
        base.Plugin.__init__(self)
        self.name = plugName
        self.plugURL = plugURL
        self.plugBase = plugBase
        self.header = plugHeader
        self.movie = movie
        if movie:
            self.description = "Film ratings from %s" % plugURL 
        self.defaults("N/A")
    
    def search(self, str, options={}):
        """ 
        Resets the results and queries the search 
        engine with the given string. Options is usually 
        the options dictionary in the builtin PluginManager.
        """
        if self.movie:
            ignoreYear = bool(options.get("ignoreYear"))
            torrent = bool(options.get("torrentFormat"))
            str = self._parse_filename(self._path2filename(str), ignoreYear, torrent)
        self.lastQuery = str
        
        self.defaults(str)
        searchStr = ' '.join((self.plugBase, str))
        try:
            self.url = base.google(searchStr)
            if self.url is not None:
                self.getinfo()
        except Exception, e:
            print e
            self.defaults(str)
        self.display = True
    
    def defaults(self, query):
        """ Resets the results to their default values. """
        self.title = query
        self.url = "(None Found)"
        
    def _path2filename(self, path):
        #e.g. "Documents\Videos\8MM [1999].avi" => "8MM [1999].avi"
        i = path.rfind('\\')
        if i==-1:
            i = path.rfind('/')
        if i!=-1:
            return path[i+1:]
        else:
            return path
    
    def _parse_filename(self, filename, ignoreYear=False, torrentFormat=False):
        str = filename 
        #e.g. "8MM [1999].avi" => "8MM 1999"
        i = str.rfind('.')
        if i!=-1 and ' ' not in str[i:]:
            str = str[:i]
        if torrentFormat:
            str = str.replace('.', ' ')
        if not ignoreYear and str.endswith(']'):
            str = str.replace(']', ')')
            str = str.replace('[', '(')
        return str

class IMDB(BasicPlugin):
    def __init__(self, gameSearch=False):
        plugBase = 'site:www.imdb.com/title'
        if gameSearch:
            plugBase = 'site:www.imdb.com/title "(VG)"'
        self.gameSearch = gameSearch
        plugURL = "IMDB.com"
        BasicPlugin.__init__(self, 
                             "IMDB", plugURL, plugBase,
                             ["Title", "Rating", "# Of Votes", "Source"])
        if self.gameSearch:
            self.description = "Game ratings from %s" % plugURL
        
    def defaults(self, query):
        self.title = query
        self.rating = "N/A"
        self.votes = "N/A"
        self.url = "(Not Found)"
    
    def list(self):
        return [self.title, self.rating, self.votes, self.url]
    
    def getinfo(self):
        """ Gets rating and other info from IMDB. """
        htmlSource = base.get_html(self.url)
        
        start, end = base.find_block(htmlSource, '<title>', '</title>')
        self.title = base.unescape(htmlSource[start:end], True)
        
        start, end = base.find_block(htmlSource, '<div class="meta">', '</div>', end)
        if start == -1 or 'awaiting' in htmlSource[start:end]:
            self.rating = "N/A"
            self.votes = "N/A" 
        else:
            end = htmlSource.find('</b>', start)
            self.rating = htmlSource[start:end].lstrip()[3:]
            start, end = base.find_block(htmlSource, 'class="tn15more">', ' votes</a>', end)
            self.votes = htmlSource[start:end]
            
class RottenTomatoes(BasicPlugin):
    def __init__(self):
        BasicPlugin.__init__(self, 
                             "Rotten Tomatoes", "RottenTomatoes.com",
                             "site:www.rottentomatoes.com/m Reviews",
                             ["Title", "T-Meter", "Top Critics",
                                "RT Community", "Source"])
        
    def defaults(self, query):
        self.title = query
        self.meter = "N/A"
        self.critics = "N/A"
        self.users = "N/A"
        self.url = "(Not Found)"
    
    def list(self):
        return [self.title, self.meter, self.critics, self.users, self.url]
    
    def getinfo(self):
        """ Gets rating and other info from RT. """
        htmlSource = base.get_html(self.url)

        start,end = base.find_block(htmlSource, 'movie_title clearfix">', '</h1>')
        self.title = htmlSource[start:end]
        
        end = htmlSource.find('tomatometer_nav', end)
        if end == -1:
            self.meter = "N/A"
            self.critics = "N/A"
            self.users = "N/A"
        else:
            results = []
            for i in range(3):
                start,end = base.find_block(htmlSource, '<a title="', '"', end)
                results.append(htmlSource[start:end])
            self.meter = results[0]
            self.critics = results[1]
            self.users = results[2]
            
class Metacritic(BasicPlugin):
    def __init__(self, gameSearch=False):
        plugBase = "site:www.metacritic.com/*/titles reviews"
        if gameSearch:
            plugBase = "site:www.metacritic.com/games/ reviews"
        self.gameSearch = gameSearch
        plugURL = "Metacritic.com"
        BasicPlugin.__init__(self, 
                             "Metacritic", plugURL, plugBase,
                             ["Title", "Metascore", "Users", "Source"])
        if self.gameSearch:
            self.description = "Game ratings from %s" % plugURL
        
    def defaults(self, query):
        self.title = query
        self.metascore = "N/A"
        self.users = "N/A"
        self.url = "(Not Found)"
            
    def list(self):
        return [self.title, self.metascore, self.users, self.url]
        
    def getinfo(self):
        htmlSource = base.get_html(self.url)
        htmlLow = htmlSource.lower()
        
        t = '<title>'
        start = htmlLow.find(t) + len(t)
        last = htmlLow.find('</title>', start)
        end = htmlLow.find(': reviews', start, last)
        if end == -1:
            end = htmlLow.find(' - reviews', start, last)
            if end == -1:
                end = last
        self.title = urllib.unquote(base.unescape(htmlSource[start:end], False))
        
        start, end = base.find_block(htmlLow, '"metascore: ', '"')
        self.metascore = htmlSource[start:end]
        
        start = htmlLow.find('<a name="users">', end)
        start, end = base.find_block(htmlLow, '<span class="subhead">', 
                                     '</span>', start)
        self.users = ''.join((htmlSource[start:end], '/10'))

class GameSpot(BasicPlugin):
    def __init__(self):
        BasicPlugin.__init__(self, 
                             "GameSpot", "GameSpot.com",
                             "site:www.gamespot.com/ review",
                             ["Title", "Score", 
                              "Critics", "Users", "Source"])
        
    def defaults(self, query):
        self.title = query
        self.score = "N/A"
        self.critics = "N/A"
        self.users = "N/A"
        self.url = "(Not Found)"
    
    def list(self):
        return [self.title, self.score, self.critics, self.users, self.url]
    
    def getinfo(self):
        """ Gets rating and other info from RT. """
        htmlSource = base.get_html(self.url)
        
        start, end = base.find_block(htmlSource, '<h2>', '</h2>')
        last = end
        self.title = htmlSource[start:end] 
        
        start, end = base.find_block(htmlSource, 'gs-score">', '</a>', end)
        if start != -1:
            self.score = htmlSource[start:end]
        else:
            end = last
        
        start, end = base.find_block(htmlSource, 'critic-score">', '</a>', end)
        if start != -1:
            sc =  htmlSource[start:end]
            start, end = base.find_block(htmlSource, 'critic-score">', '</a>', end)
            vt =  htmlSource[start:end]
            self.critics = "%s based on %s review(s)" % (sc, vt)
        else:
            end = last
        
        start, end = base.find_block(htmlSource, 'user-score">', '</a>', end)
        if start != -1:
            sc =  htmlSource[start:end]
            start, end = base.find_block(htmlSource, 'user-score">', '</a>', end)
            vt =  htmlSource[start:end]
            self.users = "%s based on %s vote(s)" % (sc, vt)
        
class GamePro(BasicPlugin):
    def __init__(self):
        BasicPlugin.__init__(self, 
                             "GamePro", "GamePro.com",
                             "site:www.gamepro.com/article/reviews/",
                             ["Title", "Score", "Users", "Source"])
        
    def defaults(self, query):
        self.title = query
        self.score = "N/A"
        self.users = "N/A"
        self.url = "(Not Found)"
    
    def list(self):
        return [self.title, self.score, self.users, self.url]
    
    def getinfo(self):
        """ Gets rating and other info from RT. """
        htmlSource = base.get_html(self.url)
        
        start, end = base.find_block(htmlSource, '<title>Review : ', 
                                     ' - from GamePro.com</title>')
        self.title = htmlSource[start:end] 
        
        start, end = base.find_block(htmlSource, '<li id="gp_score-', '"', end)
        self.score = htmlSource[start:end]
        
        start, end = base.find_block(htmlSource, '<li id="avg_', '-', end)
        userAvg =  htmlSource[start:end]
        
        start, end = base.find_block(htmlSource, 'total_', '-', end)
        userVotes = htmlSource[start:end]
        self.users = '%s average rating from %s votes' % (userAvg, userVotes)
        
class MobyGames(BasicPlugin):
    def __init__(self):
        BasicPlugin.__init__(self, 
                             "MobyGames", "MobyGames.com",
                             "site:www.mobygames.com/game/",
                             ["Title", "Source"])
        self.defaultRank = "Unknown"
        
    def defaults(self, query):
        self._list = None
        self.header = ["Title", "Rank", "Source"]
        self.title = query
        self.url = "(Not Found)"
    
    def list(self):
        if self._list is None:
            return [self.title, self.defaultRank, self.url]
        else:
            return self._list
    
    def getinfo(self):
        """ Gets rating and other info from GameStop. """
        if 'reviews/' in self.url:
            start = self.url.find('reviews/')
            self.url = self.url[:start]
        htmlSource = base.get_html(self.url)
        
        self._list = None
        
        start, end = base.find_block(htmlSource, '<title>', ' - MobyGames</title>')
        self.title = urllib.unquote(htmlSource[start:end])
        
        empty = "..."
        platforms = {}
        tag = 'id="gamePlatform">'
        start = htmlSource.find(tag, end)
        if start != -1: #assume single platform
            start += len(tag)
            start, end = base.find_block(htmlSource, '>', '</a>', start)
            p = htmlSource[start:end]
            s = [empty, empty]
            size = ('scoreBoxBig', 'scoreBoxMed')
            for i in range(2):
                start = htmlSource.find(size[i], end) + len(size[i])
                start, end = base.find_block(htmlSource, '">', '</div>', start)
                s[i] = htmlSource[start:end]
            platforms[p] = tuple(s)
        else: #assume multiple platforms
            start, last = base.find_block(htmlSource, '<tbody>', '</tbody>', end)
            if start == -1:
                raise Exception("Unable to read HTML page %s" % self.url)
            end = start
            while True:
                start, end = base.find_block(htmlSource, '<td class="left">', '</td>', end)
                if start == -1 or end >= last:
                    break
                p = htmlSource[start:end]
                s = [empty, empty]
                for i in range(2):
                    start, end = base.find_block(htmlSource, 'bold">', '</div>', end)
                    s[i] = htmlSource[start:end]
                platforms[p] = tuple(s)
        
        self.header = ["Title"]
        self._list = [self.title]
        single = len(platforms) == 1
        for k, v in platforms.iteritems():
            if single:
                arg = ''
            else:
                arg = ''.join((k, ': '))
            self.header.append("%sCritics" % arg)
            self._list.append(v[0])
            self.header.append("%sUsers" % arg)
            self._list.append(empty if v[1]==empty else ''.join((v[1], '/5')))
        self.header.append("Source")
        self._list.append(self.url)